1.回溯法简介
回溯法,又称试探法,是常用的,基本的优选搜索方法。常用于解决这一类问题:给定一定约束条件F(该约束条件常用于后面的剪枝)下求问题的一个解或者所有解。
回溯法其实是暴力枚举的一种改进,因为其会聪明的filter掉不合适的分支,大大减少了无谓的枚举。若某问题的枚举都是可行解得话,也就是没有剪枝发生,那么回溯法和暴力枚举并无二异。
该回溯法先从解空间中选取任意一个可能满足约束条件F
的点x1
,然后从满足F
的解空间中继续选择一个点x2
,直到所找到的点构成一个解S
或者找不到满足约束条件F
的点时,开始回溯。回溯到上一层节点f,再另选满足F
的解空间中的一点,继续试探。
整个过程类似于一个递归树,因此回溯法常常采用DFS
的方法来实现。不考虑约束条件F
,整个递归树的任一根节点root
到叶子节点leaf
的路径path
都是无约束条件F
的原问题的一个解。
现在考虑约束条件F
,实际就是在每次向下深入的时候,利用约束条件F
来判断当前遍历的节点是否有必要继续搜索下去,若无必要则马上回溯;有必要则继续深入,这一个过程类似于约束条件F
剪去了多余的递归分支。
回溯法解决的问题的一般特征:能够利用约束条件F
去快速判断构成一个完整解的一些局部候选信息partial candidates
是否可能最终构成一个正确的、完整的解。
2.回溯法的基本步骤
- 明确问题的解空间
S
和约束条件F
. - 利用深度优先搜索,试探可能构成一个完整解的候选节点,利用约束条件
F
进行剪枝
2.1. 找到递归的base case
2.2. 利用约束条件F
判断是否剪枝,一旦剪枝,则开始回溯(返回) - 当递归到叶节点的时候,即得到原问题在约束条件
F
下的一个解,若要得到所有的可行解,则还需要考察根节点的其他分支。
回溯法注意事项:
- 递归状态的存储和更新
- 回溯点的处理(是否应该清除该回溯点之前对递归状态产生的
side effect
) - 解的搜集
3.回溯法之经典问题
回溯法之经典问题:N皇后问题
1 | public class NQueensDemo { |
4.回溯法之经典问题:Sudoku(数独)
1 |
|